#
# netdev The gateway interface (default eth0).
# antispoof Whether to use iptables to prevent spoofing (default no).
+# dhcp Whether to alter the local DHCP configuration (default no).
#
#============================================================================
+dir=$(dirname "$0")
+. "$dir/xen-script-common.sh"
+. "$dir/xen-network-common.sh"
-
-# Exit if anything goes wrong.
-set -e
-
-# First arg is the operation.
-OP=$1
-shift
-
-# Pull variables in args in to environment.
-for arg ; do export "${arg}" ; done
+findCommand "$@"
+evalVariables "$@"
netdev=${netdev:-eth0}
# antispoofing not yet implemented
antispoof=${antispoof:-no}
+dhcp=${dhcp:-no}
+
+if [ "$dhcp" != 'no' ]
+then
+ dhcpd_conf_file=$(find_dhcpd_conf_file)
+ dhcpd_init_file=$(find_dhcpd_init_file)
+ if [ -z "$dhcpd_conf_file" ] || [ -z "$dhcpd_init_file" ]
+ then
+ echo 'Failed to find dhcpd configuration or init file.' >&2
+ exit 1
+ fi
+fi
+
+
+function dhcp_start()
+{
+ if ! grep -q "subnet 10.0.0.0" "$dhcpd_conf_file"
+ then
+ echo >>"$dhcpd_conf_file" "subnet 10.0.0.0 netmask 255.255.0.0 {}"
+ fi
+
+ "$dhcpd_init_file" restart
+}
-echo "*network-nat $OP netdev=$netdev antispoof=$antispoof" >&2
+
+function dhcp_stop()
+{
+ local tmpfile=$(mktemp)
+ grep -v "subnet 10.0.0.0" "$dhcpd_conf_file" >"$tmpfile"
+ if diff "$tmpfile" "$dhcpd_conf_file" >&/dev/null
+ then
+ rm "$tmpfile"
+ else
+ mv "$tmpfile" "$dhcpd_conf_file"
+ fi
+
+ "$dhcpd_init_file" restart
+}
op_start() {
echo 1 >/proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -o ${netdev} -j MASQUERADE
+ [ "$dhcp" != 'no' ] && dhcp_start
}
op_stop() {
+ [ "$dhcp" != 'no' ] && dhcp_stop
iptables -t nat -D POSTROUTING -o ${netdev} -j MASQUERADE
}
}
-case ${OP} in
+case "$command" in
start)
op_start
;;
;;
*)
- echo 'Unknown command: ' ${OP} >&2
+ echo "Unknown command: $command" >&2
echo 'Valid commands are: start, stop, status' >&2
exit 1
esac
# vif vif interface name (required).
# XENBUS_PATH path to this device's details in the XenStore (required).
#
+# Parameters:
+# dhcp Whether to alter the local DHCP configuration to include this
+# new host (default no).
+#
# Read from the store:
# ip list of IP networks for the vif, space-separated (default given in
# this script).
#============================================================================
+
dir=$(dirname "$0")
. "$dir/vif-common.sh"
+dhcp=${dhcp:-no}
+
+if [ "$dhcp" != 'no' ]
+then
+ dhcpd_conf_file=$(find_dhcpd_conf_file)
+ dhcpd_init_file=$(find_dhcpd_init_file)
+ if [ -z "$dhcpd_conf_file" ] || [ -z "$dhcpd_init_file" ]
+ then
+ echo 'Failed to find dhcpd configuration or init file.' >&2
+ exit 1
+ fi
+fi
+
+
+ip_from_dom()
+{
+ local domid=$(echo "$XENBUS_PATH" | sed -n 's#.*/\([0-9]*\)/[0-9]*$#\1#p')
+ local vifid=$(echo "$XENBUS_PATH" | sed -n 's#.*/[0-9]*/\([0-9]*\)$#\1#p')
+
+ local domid1=$(( $domid / 256 ))
+ local domid2=$(( $domid % 256 ))
+ vifid=$(( $vifid + 1 ))
+
+ echo "10.$domid1.$domid2.$vifid/16"
+}
+
+
+routing_ip()
+{
+ echo $(echo $1 | awk -F. '{print $1"."$2"."$3"."$4 + 127}')
+}
+
+
+dotted_quad()
+{
+ echo\
+ $(( ($1 & 0xFF000000) >> 24))\
+.$(( ($1 & 0x00FF0000) >> 16))\
+.$(( ($1 & 0x0000FF00) >> 8 ))\
+.$(( $1 & 0x000000FF ))
+}
+
+
if [ "$ip" == "" ]
then
- ip='169.254.1.1/24'
+ ip=$(ip_from_dom)
fi
-#determine ip address and netmask
+router_ip=$(routing_ip "$ip")
+
+# Split the given IP/bits pair.
vif_ip=`echo ${ip} | awk -F/ '{print $1}'`
bits=`echo ${ip} | awk -F/ '{print $2}'`
-intmask=$(( ((0xFFFFFFFF << ((32 - $bits)))) & 0xFFFFFFFF ))
-netmask=$(( (($intmask & 0xFF000000)) >> 24 ))
-netmask=$netmask.$(( (($intmask & 0x00FF0000)) >> 16 ))
-netmask=$netmask.$(( (($intmask & 0x0000FF00)) >> 8 ))
-netmask=$netmask.$(( $intmask & 0x000000FF ))
+
+# Convert $bits and $vif_ip to integers, mask appropriately to get a network
+# address, and convert them both to dotted quads.
+
+intmask=$(( (0xFFFFFFFF << (32 - $bits)) & 0xFFFFFFFF ))
+vif_int=$(( $(echo "((($vif_ip" | sed -e 's#\.#)\*256\+#g') ))
+
+netmask=$(dotted_quad $intmask)
+network=$(dotted_quad $(( $vif_int & $intmask )) )
main_ip=$(dom0_ip)
+
+dhcp_remove_entry()
+{
+ local tmpfile=$(mktemp)
+ grep -v "host Xen-${vif/./-}" "$dhcpd_conf_file" >"$tmpfile"
+ if diff "$tmpfile" "$dhcpd_conf_file" >/dev/null
+ then
+ rm "$tmpfile"
+ else
+ mv "$tmpfile" "$dhcpd_conf_file"
+ fi
+}
+
+
+dhcp_up()
+{
+ dhcp_remove_entry
+ mac=$(xenstore_read "$XENBUS_PATH/mac")
+ echo >>"$dhcpd_conf_file" \
+"host Xen-${vif/./-} { hardware ethernet $mac; fixed-address $vif_ip; option routers $router_ip; }"
+
+ "$dhcpd_init_file" restart
+}
+
+
+dhcp_down()
+{
+ dhcp_remove_entry
+ "$dhcpd_init_file" restart || true # We need to ignore failure because
+ # ISC dhcpd 3 borks if there is nothing
+ # for it to do, which is the case if
+ # the outgoing interface is not
+ # configured to offer leases and there
+ # are no vifs.
+}
+
+
case "$command" in
online)
- ifconfig ${vif} ${vif_ip} netmask ${netmask} up
+ if ip route | grep -q "dev $vif"
+ then
+ log debug "$vif already up"
+ exit 0
+ fi
+
+ do_or_die ip link set "$vif" up arp on
+ do_or_die ip addr add "$router_ip" dev "$vif"
+ do_or_die ip route add "$vif_ip" dev "$vif" src "$main_ip"
echo 1 >/proc/sys/net/ipv4/conf/${vif}/proxy_arp
- ipcmd='a'
+ [ "$dhcp" != 'no' ] && dhcp_up
;;
offline)
- ifconfig ${vif} down
- ipcmd='d'
+ [ "$dhcp" != 'no' ] && dhcp_down
+ ifconfig "$vif" down || true
;;
esac
-ip r ${ipcmd} ${ip} dev ${vif} src ${main_ip}
handle_iptable